﻿using System;
using System.Collections.Generic;
using DG.Tweening;
using DG.Tweening.Plugins.Core;
using LogSystem;
using Unity.Mathematics;
using UnityEngine;
using Yoozoo.Gameplay;
using Yoozoo.Gameplay.RTS;
using Yoozoo.Gameplay.RTS.Proto;


/// <summary>
/// 行军数据类
/// </summary>
public class MarchInfo
{
    public Vector3 BeforeForward = Vector3.forward;
    //英雄ID
    public List<int> HeroList = new List<int>(3);
    public List<int> HeroQualityList = new List<int>(3);
    public List<int> HeroRageList = new List<int>(3);
    public long Uid;
    public Vector3 LastPosition;
    public MarchEntity MarchEntity;
    public int MarchIndex;
    public MarchStatus MarchStatus;
    public MarchType MarchType;
    public int MaxRage;
    public bool IsForceMoveChild = false;
    public LuaArrAccess soldierListAccess;
    public float SetClientInBattleTime;
    private float lastStartBattleEffectTimer = 0;
    public bool IsWalkToPark = false;
    public static List<List<int>> SoldierPositionIndexArray = new List<List<int>>
    {
        new List<int> {},
        new List<int> {0},
        new List<int> {0, 1},
        new List<int> {0, 1, 2},
        new List<int> {0, 1, 2, 3},
        new List<int> {0, 1, 2, 3, 4},
        new List<int> {0, 1, 2, 3, 4, 5},
        new List<int> {0, 1, 2, 3, 4, 5, 6},
        new List<int> {0, 1, 2, 3, 4, 5, 6, 7},
        new List<int> {0, 1, 2, 3, 4, 5, 6, 7, 8},
        new List<int> {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
        new List<int> {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
        new List<int> {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
        new List<int> {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
        new List<int> {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
        new List<int> {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
        new List<int> {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
        new List<int> {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
    };

    public static List<List<int>> SoldierPositionIndexArrayMirror = new List<List<int>>
    {
        new List<int> {},
        new List<int> {0},
        new List<int> {1, 0},
        new List<int> {0, 2, 1},
        new List<int> {1, 0, 3, 2},
        new List<int> {0, 2, 1, 4, 3},
        new List<int> {0, 2, 1, 4, 3, 5},
        new List<int> {0, 2, 1, 4, 3, 6, 5},
        new List<int> {0, 2, 1, 4, 3, 6, 5, 7},
        new List<int> {0, 2, 1, 4, 3, 6, 5, 8, 7},
        new List<int> {0, 2, 1, 5, 4, 3, 9, 8, 7, 6},
        new List<int> {1, 0, 3, 2, 6, 5, 4, 10, 9, 8, 7},
        new List<int> {1, 0, 2, 4, 3, 7, 6, 5, 11, 10, 9, 8},
        new List<int> {1, 0, 2, 4, 3, 8, 7, 6, 5, 12, 11, 10, 9},
        new List<int> {1, 0, 4, 3, 2, 8, 7, 6, 5, 13, 12, 11, 10, 9},
        new List<int> {0, 2, 1, 5, 4, 3, 9, 8, 7, 6, 14, 13, 12, 11, 10},
        new List<int> {1, 0, 3, 2, 6, 5, 4, 10, 9, 8, 7, 15, 14, 13, 12, 11},
        new List<int> {2, 1, 0, 4, 3, 7, 6, 5, 11, 10, 9, 8, 16, 15, 14, 13, 12},
    };

    /// <summary>
    /// 目标阵营
    /// </summary>
    public int TargetTeam;
    /// <summary>
    /// 阵营
    /// </summary>
    public int Team = -1;
    /// <summary>
    /// 客户端行军类型
    /// </summary>
    public EMarchStatus ClientMarchStatue = EMarchStatus.Uninit;

    public bool IsSoldierCountDirty;
    private int _soldierCount = 0;

    public int SoldierCount
    {
        get { return _soldierCount; }
        set
        {
            if (value!=_soldierCount)
            {
                _soldierCount = value;
                IsSoldierCountDirty = true;
            }
        }
    }
    public Vector3 ClientAttackPosition { get; set; }
    public int InitSoldierCount = 0;
    public long BuildingUid = 0;
    public Vector3 Coordinate;//只有警察署这个值才会赋值
    public Vector3 Position
    {
        get
        {
            if (MarchEntity.IsTruckAttacking())
            {
                return MarchEntity.GetTruckAttackerPosition();
            }
            else if(MarchEntity.isTrainDefenceMarch())
            {
                return MarchEntity.GetTruckAttackerPosition();
            }
            else if (MarchEntity.RtsServerInfo != null)
            {
                if (MarchEntity.RtsServerInfo.Type == TargetCoordinateType.POLICE_OFFICE_16 || MarchEntity.RtsServerInfo.Type == TargetCoordinateType.DEFENCE_ASSEMBLY_NPC_23 
                    || MarchEntity.RtsServerInfo.Type == TargetCoordinateType.ALLIANCE_PRACTICE_BOSS_32 || MarchEntity.RtsServerInfo.Type == TargetCoordinateType.WORLD_BOSS_44 || MarchEntity.RtsServerInfo.DefenceTroop)
                {
                    return Coordinate;
                }

                if (MarchEntity.isFakeChild)
                {
                    return Coordinate;
                }
            }

            return GetPosition() + PosOffset;
        }
    }

    public Vector3 EndPosition
    {
        get
        {
            if (ClientMarchStatue == EMarchStatus.CrossingGate)
            {
                return crossingGateEndPosition;
            }
            return Segment.endPosition;
        }
    }
    public Vector3 StartPosition => Segment.startPosition;

    public Vector3 SegmentStartPosition
    {
        get
        {
            if (ClientMarchStatue == EMarchStatus.CrossingGate)
            {
                return crossingGateStartPosition;
            }
            return Segment.segmentStartPosition;
        }
    }
    public float Speed => Segment.speed;

    public float CurrentSegmentDuration
    {
        get
        {
            if (ClientMarchStatue == EMarchStatus.CrossingGate)
            {
                return BattleUtils.CrossingGateTime;
            }
            return Segment.duration;
        }
    }
    public Vector3 CurrentForward
    {
        get
        {
            if (MarchEntity.IsTruckAttacking())
            {
                return MarchEntity.GetTruckAttackerForward();
            }
            else if (ClientMarchStatue == EMarchStatus.CrossingGate)
            {
                return crossingGateForward;
            }
            return _currentForward;
        }
    }
    public Segment Segment => ArmyManager.Instance.MarchManager.GetSegment(MarchIndex);
    public float AttackRange { private set; get; }
    public long TargetId { get; private set; }
    public long BattleTargetId { get; private set; }
    //
    public long[] AttackSelfIds;
    public float FightFrameTime = 0;
    public TargetCoordinateType TargetType => _targetType;
    private Vector3 _targetPosition = Vector3.zero;
    private TargetCoordinateType _targetType;
    public TargetCoordinateType attackTargetType;
    private Vector3 _currentForward = Vector3.forward;
    public bool ServerInbattle;
    public bool IsClientInBattle;
    private bool _posMirror = false;
    private bool _troopStateVisible = true;
    private bool _isInitTroopVisible = false;
    public bool IsInBattleState => ServerInbattle || IsClientInBattle;

    public int SoldierType { get; internal set; }
    public int SoldierListLength = 0;
//    public TroopMarch serverData;
    public float3 PosOffset;

    public MarchInfo(MarchEntity marchEntity)
    {
        MarchEntity = marchEntity;
        int hashCode = Mathf.Abs(GetHashCode());
        float offset = (hashCode) / (1.0f * int.MaxValue) * 0.01f;
        PosOffset = new float3(0,1,0) * offset;
        lastStartBattleEffectTimer = 0;
    }

    public void Initialize(long tid,int team)
    {
        Uid = tid;
        Team = team;
    }

    public void SetIsInBattle(bool isInBattle)
    {
        if (isInBattle!=ServerInbattle)
        {
            if (isInBattle)
            {
                MarchManager.BattleTroopCount++;
                RoundFightPlayer.Inst.AddDirectionEffect(Uid,MarchEntity.TargetCoordinateType, MarchEntity);
                if (Team == (int)MarchTeam.Self)
                {
                    var target = MarchEntity.GetBattleTarget();
                    if (target != null)
                    {
                        RoundFightPlayer.Inst.AddDirectionEffect(target.Tid,target.TargetCoordinateType ,target, true);
                    }
                }
            }
            else
            {
                MarchManager.BattleTroopCount--;
//                BattleTargetId = 0;
                RoundFightPlayer.Inst.RemoveDirectionEffect(Uid);
                if (Team == (int)MarchTeam.Self)
                {
                    var target = MarchEntity.GetBattleTarget();
                    if (target != null)
                    {
                        var enemyTarget = target.GetBattleTarget();
                        if (enemyTarget!=null)
                        {
                            if (enemyTarget.Tid != Uid && enemyTarget.Team != (int)MarchTeam.Self)
                            {
                                if (!MarchManager.Instance.IsSelfAttack(target.Tid,target.TargetCoordinateType))
                                {
                                    RoundFightPlayer.Inst.RemoveDirectionEffect(target.Tid);
                                }
                            }
                        }
                    }
                }
            }
            if (ArmyManager.IsDebug)
            {
                Debug.LogError(Uid+" MarchInfo.ServerInBattle = " + isInBattle);
            }
        }
        ServerInbattle = isInBattle;
    }
    public void SetIsClientInBattle(bool isInBattle)
    {
        if (IsClientInBattle != isInBattle)
        {
            if (isInBattle)
            {
                if (MarchEntity.Visible && Team == (int)MarchTeam.Self && BuildingUid == 0 && 
                    MarchType!=MarchType.ASSEMBLY_OUT_12 && 
                    MarchType!=MarchType.ASSEMBLY_JOIN_11 && 
                    MarchType!=MarchType.TRADE_TRUCK_16 &&
                    MarchType!=MarchType.TRAIN_17)
                {
                    if ((Time.realtimeSinceStartup - lastStartBattleEffectTimer) > 1f)
                    {
                        RTSLuaCallCSharpManager.FlyText(1005,Position + CurrentForward * 0.5f,"",1.0f,new Vector3(),"",0);
                    }
                    lastStartBattleEffectTimer = Time.realtimeSinceStartup;
                }
                RoundFightPlayer.Inst.AddDirectionEffect(Uid,MarchEntity.TargetCoordinateType, MarchEntity);
            }
            else
            {
                RoundFightPlayer.Inst.RemoveDirectionEffect(Uid);
            }
            if (ArmyManager.IsDebug)
            {
                Debug.LogError(Uid+" MarchInfo.ClientInBattle = " + isInBattle);
            }
        }

        /*if (isInBattle)
        {
            SetClientInBattleTime = TimeUtils.GetClientTickTime();
        }*/
        IsClientInBattle = isInBattle;
    }

    public void SetLastPosition(Vector3 lastPosition)
    {
        LastPosition = lastPosition;
    }

    /// <summary>
    /// 脱战标志位，只持续一回合，效果是隐藏头像并且隐藏下一回合的飘字，如果下一回合死亡的话，合并所有伤害到普攻元素上
    /// </summary>
    public void SetIsJustLeaveBattle(bool value)
    {
        isJustLeaveBattle = value;
    }

    public bool isJustLeaveBattle = false;
   

    public void SetTeam(int team)
    {
        if (Team == team)
            return;

        Team = team;
        var marchSquare = MarchEntity.GetBattleSquare();
        marchSquare?.SetTeam(team);
    }
    
    public void SetTargetId(long targetId)
    {
        TargetId = targetId;
    }
    public void SetBattleTargetId(long targetId,TargetCoordinateType attackTargetType)
    {
        BattleTargetId = targetId;
        this.attackTargetType = attackTargetType;
    }
    public void SetAttackRange(float attackRange)
    {
        AttackRange = attackRange;
    }

    public void SetMarchStatue(EMarchStatus statue)
    {
        ClientMarchStatue = statue;
    }
    // 判断部队是否移动： 移动状态 或者 追击中就认为是在移动
    public bool IsMarchSquareMoving()
    {
        return ClientMarchStatue == EMarchStatus.WALK ||
               ClientMarchStatue == EMarchStatus.Chasing || ClientMarchStatue == EMarchStatus.Escape || ClientMarchStatue == EMarchStatus.Besiege || ClientMarchStatue == EMarchStatus.CrossingGate;
    }


    public void SetTargetPosition(Vector3 position)
    {
        _targetPosition = position;
    }

    public bool IsPositionChanged()
    {
        return Position != LastPosition;
    }

    public void SetForward(Vector3 forward)
    {
       
        if (forward == Vector3.zero)
        {
            return;
        }

        if (this._currentForward != Vector3.zero)
        {
            BeforeForward = this._currentForward;
            bool isOverTurn = Vector3.Dot(BeforeForward, forward) < MarchSequareConstant.MirrorThresholdValue;
            if (isOverTurn)
            {
               // Debug.Log(LogModule.RTS,$"{Uid}    阵型镜像。。。。dot: {Vector3.Dot(BeforeForward, forward)}。。。。。");
                _posMirror = isOverTurn ? !_posMirror : _posMirror;
            }
        }
        this._currentForward = forward;
        
    }

    public Vector3 GetTargetPosition()
    {
        MarchEntity marchTarget;
        if (BattleTargetId!=0)
        {
            marchTarget = MarchEntity.GetBattleTarget();
        }
        else
        {
            marchTarget = MarchEntity.GetTarget();
        }
        if (marchTarget != null)
        {
            return marchTarget.MarchInfo.Position;
        }
        else
        {
            //可能因为时序问题获取不到target 
            if (BattleTargetId!=0)
            {
                MarchManager.Instance.RegistTargetIdFindSourceTroop(BattleTargetId,attackTargetType, Uid,MarchEntity.TargetCoordinateType);
            }
        }
        
        //Debug.LogWarning($"uid-{Uid}  BattleTargetId = {BattleTargetId} 获取TargetPosition失败...使用当前位置朝向");
        if (_targetPosition != Vector3.zero)
        {
            return _targetPosition;
        }


        return Position + CurrentForward;
    }


    public void SetTargetTeam(int targetTeam)
    {
        TargetTeam = targetTeam;
    }

    public void SetServerMarchTypeAndStatus(MarchStatus marchStatus, MarchType marchType)
    {
        MarchStatus = marchStatus;
        MarchType = marchType;
    }

    public void SetTargetType(TargetCoordinateType targetType,TargetCoordinateType attackTargetType)
    {
        this._targetType = targetType;
        this.attackTargetType = attackTargetType;
    }
    public void Dispose()
    {
        HeroList.Clear();
        HeroRageList.Clear();
        FightFrameTime = 0;
        ServerInbattle = false;
        MarchManager.BattleTroopCount--;
        IsClientInBattle = false;
        _currentForward = default;
        Team = -1;
        ClientMarchStatue = EMarchStatus.Uninit;
        BeforeForward = Vector3.forward;
        LastPosition = default;
        BattleTargetId = 0;
        TargetId = 0;
        SoldierCount = 0;
        InitSoldierCount = 0;
        BuildingUid = 0;
        _isInitTroopVisible = false;
        SoldierType = 0;
        MarchType = MarchType.INIT;
        MarchStatus = MarchStatus.INIT_0;
        MaxRage = 0;
        SoldierListLength = 0;
        isJustLeaveBattle = false;
        _troopStateVisible = true;
        marchSquareVisibleDirty = false;
        lastStartBattleEffectTimer = 0;
    }
    private float3 GetPosition()
    {
        //如果是正在跨关卡
        if (ClientMarchStatue == EMarchStatus.CrossingGate)
        {
            return crossingGatePosition;
        }
        //判断segment是否有效
        if (Segment.Valid())
        {
            return Segment.clientPosition;
        }
        return Coordinate;
    }

    private float3 crossingGatePosition;
    private float3 crossingGateForward;
    private float3 crossingGateStartPosition;
    private float3 crossingGateEndPosition;
    public float CrossingGateStartClientTime;

    private float crossingGatePercent;
    private float crossingGateDuration;
    public void StartCrossingGate(bool isForce = false)
    {
        var crossDetail = MarchEntity.RtsServerInfo.crossDetail;
        var start = crossDetail.start.ToFloat3();
        var end = crossDetail.end.ToFloat3();
        crossingGateForward = end - start;
        crossingGateStartPosition = start;
        crossingGateEndPosition = end;
        CrossingGateStartClientTime = TimeUtils.GetClientTickTimeMS() - (TimeUtils.GetServerTimeMs() - crossDetail.startTime);
        var percent = (TimeUtils.GetServerTimeMs() - crossDetail.startTime) / (BattleUtils.CrossingGateTime * 1000);
        if (percent > 1)
        {
            percent = 1;
        }
        
        var duration = BattleUtils.CrossingGateTime - (TimeUtils.GetServerTimeMs() - crossDetail.startTime) / 1000f;
        crossingGateDuration = duration;
        var startPosition = Segment.clientPosition + PosOffset;
        if (isForce || Vector3.Distance(Segment.clientPosition,start) > 3)
        {
            startPosition = start;
        }
        if (percent > 0.3f)
        {
            crossingGatePercent = percent;
            crossingGateStartPosition = startPosition + PosOffset;
            DOTween.To(() => { return crossingGatePercent; }, (v) =>
                {
                    crossingGatePercent = v;
                }, 1,
                duration).SetEase(Ease.OutCubic);
        }
        else
        {
            crossingGatePercent = 0;
            crossingGateStartPosition = startPosition + PosOffset;
            DOTween.To(() => { return crossingGatePercent; }, (v) =>
                {
                    //Debug.LogError(Uid+"过桥"+v);
                    crossingGatePercent = v;
                }, 1,
                duration).SetEase(Ease.InOutCubic);
        }
        
    }
    
    public void UpdateCrossingGate()
    {
        var crossDetail = MarchEntity.RtsServerInfo.crossDetail;
        var start = crossingGateStartPosition;
        var end = crossingGateEndPosition;
        crossingGateForward = end - start;
        if (crossingGatePercent >= 1)
        {
            MarchEntity.EndCrossingGate();
            ClientMarchStatue = EMarchStatus.WALK;
        }
        crossingGatePosition = BattleUtils.Lerp(start, end, crossingGatePercent);
    }
    
    public int GetSoldierPositionIndex(int modelIndex)
    {
        try
        {
            int count = this.MarchEntity.formationPos.Count;
            if (_posMirror)
            {
                return SoldierPositionIndexArrayMirror[count][modelIndex];
            }
            else
            {
                return SoldierPositionIndexArray[count][modelIndex];
            }
        }
        catch (Exception E)
        {
            Debug.Log(LogModule._Default_,$" {Uid} getSoldierPoserror   modelIndex = {modelIndex}  count = {this.MarchEntity.formationPos.Count}");
            return 0;
        }
     
    }
/// <summary>
///  是否需要显示部队， 非守城部队， 且不在驻扎
/// </summary>
/// <returns></returns>
    public bool NeedShowSquare()
    {
        return _troopStateVisible;
    }

    public bool SetTroopStateVisible(bool visible)
    {
        if (!_isInitTroopVisible)
        {
            _isInitTroopVisible = true;
            _troopStateVisible = visible;
            return true;
        }

        if (_isInitTroopVisible)
        {
            if (visible!= _troopStateVisible)
            {
                _troopStateVisible = visible;
                return true;
            }

        }

        return false;
    }

    //切换lod时会修改可见度，设置藏标记
    public bool marchSquareVisibleDirty;

    public float besiegeRadius;
}
